#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <D3dx9math.h>
#include <D3DVoxelTechniqueTwo.h>
#include <D3DVoxelFormats.h>
#include <D3DShaderCache.h>
#include <DXDevice.h>
D3DVoxelTechniqueTwo::D3DVoxelTechniqueTwo(ID3D11Device *pDevice, ID3D11DeviceContext *pImmediateContext) : D3DVoxelTechniqueOne(pDevice, pImmediateContext)
{

	m_pVSListNonempty = NULL;
	m_pGSListNonempty = NULL;
	m_pVSGenVertices = NULL;
	m_pGSGenVertices = NULL;
	m_pVSCalcVertices = NULL;
	m_pGSCalcVertices = NULL;
	m_pVSSplat = NULL;
	m_pGSSplat = NULL;
	m_pVSGenIndices = NULL;
	m_pGSGenIndices = NULL;
}



void D3DVoxelTechniqueTwo::Release(void)
{

	if( m_pVSListNonempty ) m_pVSListNonempty ->Release();
	if( m_pGSListNonempty ) m_pGSListNonempty->Release();

	if( m_pVSGenVertices ) m_pVSGenVertices ->Release();
	if( m_pGSGenVertices ) m_pGSGenVertices->Release();

	if( m_pVSCalcVertices ) m_pVSCalcVertices->Release();

	//if( m_pVoxelTextureSRV ) m_pVoxelTextureSRV->Release();
	if( m_pGSCalcVertices ) m_pGSCalcVertices->Release();

	if( m_pVSSplat ) m_pVSSplat->Release();
	if( m_pGSSplat ) m_pGSSplat->Release();

	if(  m_pVSGenIndices ) m_pVSGenIndices->Release();
	if( m_pGSGenIndices ) m_pGSGenIndices->Release();
	D3DVoxelTechniqueOne::Release();

}
HRESULT D3DVoxelTechniqueTwo::ComputeIsosurface(D3DVoxelChunk * pChunk)
{
	ID3D11Query *query, *pipeQuery;
	D3D11_QUERY_DESC queryDesc;

	queryDesc.MiscFlags = 0;
	queryDesc.Query = D3D11_QUERY_SO_STATISTICS;
	HRESULT hhrr = m_pDevice->CreateQuery(&queryDesc, &query);

	queryDesc.Query = D3D11_QUERY_PIPELINE_STATISTICS;
	hhrr = m_pDevice->CreateQuery(&queryDesc, &pipeQuery);
	D3D11_QUERY_DATA_PIPELINE_STATISTICS pipeStats;
	D3D11_QUERY_DATA_SO_STATISTICS soStats;
	
	m_pImmediateContext->Begin(query);
	ComputeVoxelMarkers(pChunk);
	m_pImmediateContext->End(query);
	while( S_OK != m_pImmediateContext->GetData(query, &soStats, query->GetDataSize(), 0 ) );
	DXDevice::Instance()->m_pSODebug->DebugBuffer(pChunk->m_pVoxelMarkers);


	m_pImmediateContext->Begin(query);
	m_pImmediateContext->Begin(pipeQuery);
	ComputeEdgeMarkers(pChunk);
	m_pImmediateContext->End(pipeQuery);
	m_pImmediateContext->End(query);
	while( S_OK != m_pImmediateContext->GetData(pipeQuery, &pipeStats, pipeQuery->GetDataSize(), 0 ) );
	while( S_OK != m_pImmediateContext->GetData(query, &soStats, query->GetDataSize(), 0 ) );
	DXDevice::Instance()->m_pSODebug->DebugBuffer(pChunk->m_pEdgeMarkers);
	

	m_pImmediateContext->Begin(query);
	ComputeVertices(pChunk);
	m_pImmediateContext->End(query);
	while( S_OK != m_pImmediateContext->GetData(query, &soStats, query->GetDataSize(), 0 ) );
	DXDevice::Instance()->m_pSODebug->DebugBuffer(pChunk->m_pVoxelMeshBuffer);

	

	m_pImmediateContext->Begin(pipeQuery);
	ComputeVertexIDVolume(pChunk);
	m_pImmediateContext->End(pipeQuery);
	while( S_OK != m_pImmediateContext->GetData(pipeQuery, &pipeStats, pipeQuery->GetDataSize(), 0 ) );
	DXDevice::Instance()->m_pSODebug->DebugTexture(pChunk->m_pVertexIDVolume);
	SetRenderTarget(NULL);

	pChunk->InitIndexBuffer(100);//pipeStats.PSInvocations);
	m_pImmediateContext->Begin(query);
	ComputeIndices(pChunk);
	m_pImmediateContext->End(query);
	while( S_OK != m_pImmediateContext->GetData(query, &soStats, query->GetDataSize(), 0 ) );
	DXDevice::Instance()->m_pSODebug->DebugBuffer(pChunk->m_pIndexBuffer);
	
	return S_OK;
	
}

HRESULT D3DVoxelTechniqueTwo::ComputeVoxelMarkers(D3DVoxelChunk * pChunk)
{
	HRESULT hr = S_OK;
	// set the stream-out buffer
	ID3D11Buffer* soBufferList[1] = {pChunk->m_pVoxelMarkers};
	UINT soBufferOfs[1] = {0};
	m_pImmediateContext->SOSetTargets(1, soBufferList, soBufferOfs);

	// Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pVertexLayout );

	// Set vertex buffer
    UINT stride = sizeof( VoxelVertexPlaceholder );
    UINT offset = 0;
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &m_pVertexBuffer, &stride, &offset );

	m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
	m_pImmediateContext->VSSetShader( m_pVSListNonempty, NULL, 0 );
	m_pImmediateContext->VSSetShaderResources( 1, 1, &(pChunk->m_pVoxelTextureSRV ));
	m_pImmediateContext->VSSetSamplers( 1, 1, &m_pVoxelSamplerLinear );

	// use the same geometry shader but bind a different voxel data texture.
	m_pImmediateContext->GSSetShader( m_pGSListNonempty, NULL, 0 );
	

	m_pImmediateContext->PSSetShader( NULL, NULL, 0 );

	m_pImmediateContext->Draw(D3DVoxelConstants::NonOverlappedVoxelCount *
		D3DVoxelConstants::NonOverlappedVoxelCount *
		D3DVoxelConstants::NonOverlappedVoxelCount,0);
	pChunk->m_bMarkedDirty = false;
	return S_OK;

}
HRESULT D3DVoxelTechniqueTwo::ComputeEdgeMarkers(D3DVoxelChunk * pChunk)
{
	HRESULT hr = S_OK;
	// set the stream-out buffer
	ID3D11Buffer* soBufferList[1] = {pChunk->m_pEdgeMarkers};
	UINT soBufferOfs[1] = {0};
	m_pImmediateContext->SOSetTargets(1, soBufferList, soBufferOfs);


	// Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pMarkerLayout );

	// Set vertex buffer
    UINT stride = 16;
    UINT offset = 0;
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &(pChunk->m_pVoxelMarkers), &stride, &offset );

	m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
	m_pImmediateContext->VSSetShader( m_pVSGenVertices, NULL, 0 );
	//m_pImmediateContext->VSSetShaderResources( 1, 1, &(pChunk->m_pVoxelTextureSRV ));
	//m_pImmediateContext->VSSetSamplers( 1, 1, &m_pVoxelSamplerLinear );

	// use the same geometry shader but bind a different voxel data texture.
	m_pImmediateContext->GSSetShader( m_pGSGenVertices, NULL, 0 );
	

	m_pImmediateContext->PSSetShader( NULL, NULL, 0 );

	m_pImmediateContext->DrawAuto();

	
	/*m_pImmediateContext->Draw(D3DVoxelConstants::NonOverlappedVoxelCount *
		D3DVoxelConstants::NonOverlappedVoxelCount *
		D3DVoxelConstants::NonOverlappedVoxelCount,0);*/

	return S_OK;

}
void D3DVoxelTechniqueTwo::SetRenderTarget(D3DVoxelChunk * pChunk)
{
	if( pChunk == NULL)
	{
		m_pImmediateContext->OMSetRenderTargets(1, &(DXDevice::Instance()->m_pOriginalRTV), DXDevice::Instance()->m_pOriginalDSV);
		D3D11_VIEWPORT vp;
		vp.Width = DXDevice::Instance()->m_ScreenWidth;
		vp.Height = DXDevice::Instance()->m_ScreenHeight;
		vp.MinDepth = 0.0f;
		vp.MaxDepth = 1.0f;
		vp.TopLeftX = 0;
		vp.TopLeftY = 0;
		m_pImmediateContext->RSSetViewports( 1, &vp );
	}
	else
	{
		m_pImmediateContext->OMSetRenderTargets(1, &(pChunk->m_pVertexIDVolumeRTV), NULL);
		D3D11_VIEWPORT vp;
		vp.Width = D3DVoxelConstants::VoxelsPerChunkAxis * 3;
		vp.Height = D3DVoxelConstants::VoxelsPerChunkAxis;
		vp.MinDepth = 0.0f;
		vp.MaxDepth = 1.0f;
		vp.TopLeftX = 0;
		vp.TopLeftY = 0;
		m_pImmediateContext->RSSetViewports( 1, &vp );
	}
	
}
HRESULT D3DVoxelTechniqueTwo::ComputeVertices(D3DVoxelChunk * pChunk)
{
	HRESULT hr = S_OK;

	// set the stream-out buffer
	ID3D11Buffer* soBufferList[1] = {pChunk->m_pVoxelMeshBuffer};
	UINT soBufferOfs[1] = {0};
	m_pImmediateContext->SOSetTargets(1, soBufferList, soBufferOfs);


	// Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pMarkerLayout );

	// Set vertex buffer
    UINT stride = 16;
    UINT offset = 0;
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &(pChunk->m_pEdgeMarkers), &stride, &offset );

	m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
	m_pImmediateContext->VSSetShader( m_pVSCalcVertices, NULL, 0 );
	m_pImmediateContext->VSSetShaderResources( 1, 1, &(pChunk->m_pVoxelTextureSRV ));
	m_pImmediateContext->VSSetSamplers( 1, 1, &m_pVoxelSamplerLinear );

	// use the same geometry shader but bind a different voxel data texture.
	m_pImmediateContext->GSSetShader( m_pGSCalcVertices, NULL, 0 );
	

	m_pImmediateContext->PSSetShader( NULL, NULL, 0 );

	m_pImmediateContext->DrawAuto();
	return hr;

}
HRESULT D3DVoxelTechniqueTwo::ComputeVertexIDVolume(D3DVoxelChunk * pChunk)
{
	HRESULT hr = S_OK;

	SetRenderTarget(pChunk);

	// clear the stream-out buffer settings
	ID3D11Buffer* soBufferList[1] = {NULL};
	UINT soBufferOfs[1] = {0};
	m_pImmediateContext->SOSetTargets(0, NULL, NULL);

	// Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pSplatInputLayout );

	// Set vertex buffer
    UINT stride = 16;
    UINT offset = 0;
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &(pChunk->m_pEdgeMarkers), &stride, &offset );

	m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
	m_pImmediateContext->VSSetShader( m_pVSSplat, NULL, 0 );

	m_pImmediateContext->GSSetShader( m_pGSSplat, NULL, 0 );

	m_pImmediateContext->PSSetShader( m_pPSSplat, NULL, 0 );

	m_pImmediateContext->DrawAuto();//(4, 0);
	return hr;

}
void D3DVoxelTechniqueTwo::ComputeIndices(D3DVoxelChunk * pChunk)
{
	
	// set the stream-out buffer
	ID3D11Buffer* soBufferList[1] = {pChunk->m_pIndexBuffer};
	UINT soBufferOfs[1] = {0};
	m_pImmediateContext->SOSetTargets(1, soBufferList, soBufferOfs);

	// Set the input layout
	m_pImmediateContext->IASetInputLayout( m_pMarkerLayout );

	// Set vertex buffer
    UINT stride = 16;
    UINT offset = 0;
    m_pImmediateContext->IASetVertexBuffers( 0, 1, &(pChunk->m_pVoxelMarkers), &stride, &offset );

	m_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_POINTLIST );
	m_pImmediateContext->VSSetShader( m_pVSGenIndices, NULL, 0 );

	m_pImmediateContext->GSSetShader( m_pGSGenIndices, NULL, 0 );
	m_pImmediateContext->GSSetShaderResources( 0, 1, &(pChunk->m_pVertexIDVolumeSRV ));
	//m_pImmediateContext->GSSetSamplers( 0, 1, &m_pVertexIDVolumeSampler );

	m_pImmediateContext->PSSetShader( NULL, NULL, 0 );

	m_pImmediateContext->DrawAuto();
}


HRESULT D3DVoxelTechniqueTwo::InitMCStage3Shaders(void)
{
	HRESULT hr = S_OK;
    // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"MCVoxelMarkers.fx", "VS", "vs_5_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCVoxelMarkers shader cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	
    // Create the vertex shader
	
    hr = m_pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSListNonempty );
    if( FAILED( hr ) )
    {    
        pVSBlob->Release();
        return hr;
    }

    // Define the input layout
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "POSITION", 0,  DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
    hr = m_pDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
                                          pVSBlob->GetBufferSize(), &m_pVertexLayout );
    pVSBlob->Release();
    if( FAILED( hr ) )
        return hr;

    // Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pVertexLayout );
	

	// Compile the geometry shader
    ID3DBlob* pGSBlob = NULL;
    hr = CompileShaderFromFile( L"MCVoxelMarkers.fx", "GS", "gs_5_0", &pGSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCVoxelMarkers file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	

	// create a geometry shader with stream-out
	D3D11_SO_DECLARATION_ENTRY pDescSODecl []= 
	{
        { 0, "TEXCOORD", 0, 0, 1, 0},
    };
	UINT strides[1] = {sizeof( pDescSODecl )};
	hr = m_pDevice->CreateGeometryShaderWithStreamOutput( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), pDescSODecl, 1, strides, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &m_pGSListNonempty );

    
    if( FAILED( hr ) )
        return hr;

	pGSBlob->Release();

	
    return hr;

}
HRESULT D3DVoxelTechniqueTwo::InitMCShaders(void)
{
	HRESULT hr = S_OK;
	hr = InitMCStage3Shaders();
	if( hr != S_OK )
		return hr;
	hr = InitMCStage3_2Shaders();
	if( hr != S_OK )
		return hr;

	hr = InitMCStage3_3Shaders();
	if( hr != S_OK )
		return hr;

	hr = InitMCStage3_4Shaders();
	if( hr != S_OK )
		return hr;

	hr = InitMCStage3_5Shaders();
	if( hr != S_OK )
		return hr;
	
	return hr;
}
HRESULT D3DVoxelTechniqueTwo::InitMCStage3_2Shaders(void)
{
	HRESULT hr = S_OK;
    // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"MCEdgeMarkers.fx", "VS", "vs_5_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCEdgeMarkers shader cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	
    // Create the vertex shader
	
    hr = m_pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSGenVertices );
    if( FAILED( hr ) )
    {    
        pVSBlob->Release();
        return hr;
    }

    // Define the input layout
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "TEXCOORD", 0,  DXGI_FORMAT_R32_UINT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
    hr = m_pDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
                                          pVSBlob->GetBufferSize(), &m_pMarkerLayout );
    pVSBlob->Release();
    if( FAILED( hr ) )
        return hr;

    // Set the input layout
    m_pImmediateContext->IASetInputLayout( m_pMarkerLayout );
	

	// Compile the geometry shader
    ID3DBlob* pGSBlob = NULL;
    hr = CompileShaderFromFile( L"MCEdgeMarkers.fx", "GS", "gs_5_0", &pGSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCEdgeMarkers file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	

	// create a geometry shader with stream-out
	D3D11_SO_DECLARATION_ENTRY pDescSODecl []= 
	{
        { 0, "TEXCOORD", 0, 0, 1, 0},
    };
	UINT strides[1] = {sizeof( pDescSODecl )};
	hr = m_pDevice->CreateGeometryShaderWithStreamOutput( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), pDescSODecl, 1, strides, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &m_pGSGenVertices );

    
    if( FAILED( hr ) )
        return hr;

	pGSBlob->Release();


    return hr;

}
HRESULT D3DVoxelTechniqueTwo::InitMCStage3_3Shaders(void)
{
	HRESULT hr = S_OK;
    // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"MCCalcVertices.fx", "VS", "vs_5_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCCalcVertices shader cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	
    // Create the vertex shader
	
    hr = m_pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSCalcVertices );
    if( FAILED( hr ) )
    {    
        pVSBlob->Release();
        return hr;
    }

	// Compile the geometry shader
    ID3DBlob* pGSBlob = NULL;
    hr = CompileShaderFromFile( L"MCCalcVertices.fx", "GS", "gs_5_0", &pGSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCCalcVertices file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	

	// create a geometry shader with stream-out
	D3D11_SO_DECLARATION_ENTRY pDescSODecl []= 
	{
        { 0, "SV_POSITION", 0, 0, 4, 0},
		{ 0, "NORMAL", 0, 0, 3, 0},
        { 0, "COLOR", 0, 0, 4, 0},
    };
	UINT strides[1] = {sizeof( pDescSODecl )};
	hr = m_pDevice->CreateGeometryShaderWithStreamOutput( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), pDescSODecl, 3, strides, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &m_pGSCalcVertices );

    
    if( FAILED( hr ) )
        return hr;

	pGSBlob->Release();


    return hr;

}

HRESULT D3DVoxelTechniqueTwo::InitMCStage3_4Shaders(void)
{
	HRESULT hr = S_OK;
    // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"MCVertexSplat.fx", "VS", "vs_5_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCVertexSplat shader cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	
    // Create the vertex shader
	
    hr = m_pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSSplat );
    if( FAILED( hr ) )
    {    
        pVSBlob->Release();
        return hr;
    }

	// Define the input layout
    D3D11_INPUT_ELEMENT_DESC layout[] =
    {
        { "TEXCOORD", 0,  DXGI_FORMAT_R32_UINT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };
    UINT numElements = ARRAYSIZE( layout );

    // Create the input layout
    hr = m_pDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
                                          pVSBlob->GetBufferSize(), &m_pSplatInputLayout );
    pVSBlob->Release();
    if( FAILED( hr ) )
        return hr;


	// Compile the geometry shader
    ID3DBlob* pGSBlob = NULL;
    hr = CompileShaderFromFile( L"MCVertexSplat.fx", "GS", "gs_5_0", &pGSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCVertexSplat file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	hr = m_pDevice->CreateGeometryShader( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), NULL, &m_pGSSplat );

    if( FAILED( hr ) )
        return hr;

	pGSBlob->Release();

	// Compile the pixel shader
    ID3DBlob* pPSBlob = NULL;
    hr = CompileShaderFromFile( L"MCVertexSplat.fx", "PS", "ps_5_0", &pPSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCVertexSplat file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	hr = m_pDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &m_pPSSplat );
    if( FAILED( hr ) )
    {    
        pPSBlob->Release();
        return hr;
    }
	pPSBlob->Release();

    return hr;

	

}
HRESULT D3DVoxelTechniqueTwo::InitMCStage3_5Shaders(void)
{
	HRESULT hr = S_OK;
	// Create the sampler state
    D3D11_SAMPLER_DESC VertexIDVolumeSamplerDesc;
    ZeroMemory( &VertexIDVolumeSamplerDesc, sizeof(VertexIDVolumeSamplerDesc) );
    VertexIDVolumeSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
    VertexIDVolumeSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
    VertexIDVolumeSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
    VertexIDVolumeSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
    VertexIDVolumeSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    VertexIDVolumeSamplerDesc.MinLOD = 0;
    VertexIDVolumeSamplerDesc.MaxLOD = 1;
    hr = m_pDevice->CreateSamplerState( &VertexIDVolumeSamplerDesc, &m_pVertexIDVolumeSampler );
    if( FAILED( hr ) )
        return hr;

	 // Compile the vertex shader
    ID3DBlob* pVSBlob = NULL;
    hr = CompileShaderFromFile( L"MCGenIndices.fx", "VS", "vs_5_0", &pVSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCGenIndices shader cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	
    // Create the vertex shader
	
    hr = m_pDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &m_pVSGenIndices );
    if( FAILED( hr ) )
    {    
        pVSBlob->Release();
        return hr;
    }

	// Compile the geometry shader
    ID3DBlob* pGSBlob = NULL;
    hr = CompileShaderFromFile( L"MCGenIndices.fx", "GS", "gs_5_0", &pGSBlob );
    if( FAILED( hr ) )
    {
        MessageBox( NULL,
                    L"The MCGenIndices file cannot be compiled.", L"Error", MB_OK );
        return hr;
    }
	

	// create a geometry shader with stream-out
	D3D11_SO_DECLARATION_ENTRY pDescSODecl []= 
	{
        { 0, "nigs", 0, 0, 1, 0},

		/*{ 0, "too", 0, 0, 1, 0},
		{ 0, "slee", 0, 0, 1, 0},
		{ 0, "fore", 0, 0, 1, 0},*/
    };
	UINT strides[1] = {sizeof( pDescSODecl )};
	hr = m_pDevice->CreateGeometryShaderWithStreamOutput( pGSBlob->GetBufferPointer(), pGSBlob->GetBufferSize(), pDescSODecl, 1, strides, 1, D3D11_SO_NO_RASTERIZED_STREAM, NULL, &m_pGSGenIndices );

    
    if( FAILED( hr ) )
        return hr;

	pGSBlob->Release();
	return hr;
}